package com.corechina.apex_osswords.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.corechina.apex_osswords.common.APEXOSSWordsException;
import com.corechina.apex_osswords.common.Constant;
import com.corechina.apex_osswords.common.JwtUtil;
import com.corechina.apex_osswords.common.Response;
import com.corechina.apex_osswords.domain.dao.CoreEnterpriseEngineerMapper;
import com.corechina.apex_osswords.domain.dao.SysUserMapper;
import com.corechina.apex_osswords.domain.dao.SysUserTokenMapper;
import com.corechina.apex_osswords.domain.dto.TokenNeedFieldDto;
import com.corechina.apex_osswords.domain.entity.SysUser;
import com.corechina.apex_osswords.domain.entity.SysUserToken;
import com.corechina.apex_osswords.domain.vo.SysLoginInfoVo;
import com.corechina.apex_osswords.service.ISysUserTokenService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;

/**
 * <p>
 * 用户token表 服务实现类
 * </p>
 *
 * @author cc
 * @since 2022-03-03
 */
@Service
public class SysUserTokenServiceImpl extends ServiceImpl<SysUserTokenMapper, SysUserToken> implements ISysUserTokenService {

    private final static int EXPIRE = 3600 * 12;

    public final static String LOGOUT = "logout";

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysUserTokenMapper sysUserTokenMapper;

    @Autowired
    private CoreEnterpriseEngineerMapper coreEnterpriseEngineerMapper;

    @Override
    public SysLoginInfoVo login(SysUser sysUser, Integer loginType) {
        SysLoginInfoVo sysLoginInfoVo = sysUserMapper.getUserInfoByLoginName(sysUser.getLoginName());
        if( sysUser.getPwd().equals(new Md5Hash(new Md5Hash("oneCard@1234").toString(), sysUser.getSalt()).toString())){
            sysLoginInfoVo.setNeedEditPwd(1);
        }
        // 判断已登录，不重复登录（如不判断，注释此段代码，如需根据登录类型判断，使用form.getLoginType()判断）
        SysUserToken sysUserToken = sysUserTokenMapper.getByUserId(sysUser.getId(),loginType);
        if (sysUserToken != null && !SysUserTokenServiceImpl.LOGOUT.equals(sysUserToken.getToken()) && !sysUserToken.getLoginType().equals(loginType)) {
            //判断token是否过期
            if (sysUserToken.getExpireTime().getTime() > System.currentTimeMillis()) {
                SysLoginInfoVo sysLoginInfoVo2 = new SysLoginInfoVo(sysUserToken.getToken(), sysLoginInfoVo, sysUserToken.getExpireTime());
                sysUserToken = new SysUserToken(sysUser.getId(),loginType,new Date());
                if (sysUserTokenMapper.updateUserTokenInfo(sysUserToken) > 0) {
                    return sysLoginInfoVo2;
                }else {
                    return null;
                }
            }
        }

        TokenNeedFieldDto tokenNeedFieldDto = new TokenNeedFieldDto();
        tokenNeedFieldDto.setId(sysUser.getId());
        tokenNeedFieldDto.setName(sysUser.getUserName());
        tokenNeedFieldDto.setSecret(sysUser.getPwd());
        //生成token，并保存到数据库
        sysUserToken = this.saveToken(tokenNeedFieldDto,loginType);
        if (sysUserToken != null) {
            SysLoginInfoVo sysLoginInfoVo2 = new SysLoginInfoVo(sysUserToken.getToken(), sysLoginInfoVo, sysUserToken.getExpireTime());
            return sysLoginInfoVo2;
        }
        return null;
    }

    @Override
    public SysUserToken saveToken(TokenNeedFieldDto tokenNeedFieldDto, Integer loginType) {
        String token = JwtUtil.sign(tokenNeedFieldDto);
        //当前时间
        Date now = new Date();
        //过期时间
        Date expireTime = new Date(now.getTime() + EXPIRE * 1000);

        //判断是否生成过token
        SysUserToken sysUserToken = sysUserTokenMapper.getByUserId(tokenNeedFieldDto.getId(),loginType);

        if(loginType == null){
            loginType = sysUserToken.getLoginType();
        }
        if (sysUserToken == null) {
            sysUserToken = new SysUserToken();
            sysUserToken.setUserId(tokenNeedFieldDto.getId());
            sysUserToken.setToken(token);
            sysUserToken.setLoginType(loginType);
            sysUserToken.setSecret(tokenNeedFieldDto.getSecret());
            sysUserToken.setUpdateTime(now);
            sysUserToken.setExpireTime(expireTime);
            if(sysUserToken.getEnterpriseId() == null && loginType.equals(1)){
                sysUserToken.setEnterpriseId(coreEnterpriseEngineerMapper.getOneByEngineerId(tokenNeedFieldDto.getId()));
            }
            //保存token
            if (sysUserTokenMapper.insert(sysUserToken) > 0) {
                return sysUserToken;
            }
        } else {
            sysUserToken.setToken(token);
            sysUserToken.setLoginType(loginType);
            sysUserToken.setSecret(tokenNeedFieldDto.getSecret());
            sysUserToken.setUpdateTime(now);
            sysUserToken.setExpireTime(expireTime);
            if(sysUserToken.getEnterpriseId() == null && loginType.equals(1)){
                sysUserToken.setEnterpriseId(coreEnterpriseEngineerMapper.getOneByEngineerId(tokenNeedFieldDto.getId()));
            }
            //更新token
            if (sysUserTokenMapper.updateUserTokenInfo(sysUserToken) > 0) {
                return sysUserToken;
            }
        }
        return null;
    }

    @Override
    public Boolean logout(Integer userId) {
        Integer loginType = Constant.LoginType.CLIENT_LOGIN.getCode();
        return logout(userId,loginType);
    }

    private Boolean logout(Integer userId, Integer loginType) {
        SysUserToken sysUserToken = sysUserTokenMapper.getByUserId(userId,loginType);
        if(loginType == null){
            loginType = Constant.LoginType.CLIENT_LOGIN.getCode();
        }
        if(loginType.equals(sysUserToken.getLoginType())){
            //修改token
            Date now = new Date();
            sysUserToken.setUserId(userId);
            sysUserToken.setToken(LOGOUT);
            sysUserToken.setSecret(LOGOUT);
            sysUserToken.setUpdateTime(now);
            sysUserToken.setExpireTime(now);
            if (sysUserTokenMapper.updateUserTokenInfo(sysUserToken) > 0) {
                Subject subject = SecurityUtils.getSubject();
                subject.logout();
                return true;
            }
        }else {
            throw new APEXOSSWordsException("用户使用其他方式登录中");
        }
        return false;
    }
}
